package cn.xopencode.oss.service.permission;

import cn.hutool.core.collection.CollectionUtil;
import cn.xopencode.common.framework.exception.GlobalException;
import cn.xopencode.common.framework.util.CollectionUtils;
import cn.xopencode.common.framework.exception.util.ServiceExceptionUtil;
import cn.xopencode.oss.dal.mysql.dataobject.permission.PositionResourceDO;
import cn.xopencode.oss.dal.mysql.dataobject.permission.ResourceDO;
import cn.xopencode.oss.dal.mysql.mapper.admin.AdminMapper;
import cn.xopencode.oss.dal.mysql.mapper.permission.AdminPositionMapper;
import cn.xopencode.oss.dal.mysql.mapper.permission.ResourceMapper;
import cn.xopencode.oss.dal.mysql.mapper.permission.PositionMapper;
import cn.xopencode.oss.dal.mysql.mapper.permission.PositionResourceMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static cn.xopencode.common.framework.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;
import static cn.xopencode.oss.enums.SystemErrorCodeConstants.*;

/**
 * 职位资源权限 Service
 */
@Service
@Slf4j
public class PermissionService {

    //@Autowired
    //private AdminMapper adminMapper;
    @Autowired
    private PositionMapper positionMapper;
    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private AdminPositionMapper adminPositionMapper;
    @Autowired
    private PositionResourceMapper positionResourceMapper;

    /**
     * 获得职务拥有的资源编号
     * @param positionId 职务编号
     * @return 资源编号列表
     */
    public Set<String> listPositionResourceIds(String positionId) {
        //先从Redis缓存中加载，加载不到的，再从数据库加载

        //从数据库加载
        List<PositionResourceDO> positionResourceDOS = positionResourceMapper.selectListByPositionId(positionId);
        return CollectionUtils.convertSet(positionResourceDOS, PositionResourceDO::getResourceId);
    }
    /**
     * 获得员工拥有的职务编号
     *
     * @param adminId 管理员编号
     * @return 资源编号列表
     */
    public Set<String> listAdminPositionIds(String adminId) {
        return null;
    }
    /**
     * 赋予職位资源
     *
     * @param positionId 職位编号
     * @param resourceIds 资源编号列表
     */
    @Transactional
    public void assignPositionResource(String positionId, Set<String> resourceIds) {
        // 校验职务是否存在
        if (positionMapper.selectById(positionId) == null) {
            throw ServiceExceptionUtil.exception(Position_NOT_EXISTS);
        }
        // 校验是否有不存在的资源
        if (!CollectionUtils.isEmpty(resourceIds)) {
            int dbResourceSize = resourceMapper.selectCountByIdsAndType(resourceIds, null);
            if (resourceIds.size() != dbResourceSize) {
                throw ServiceExceptionUtil.exception(PERMISSION_Position_ASSIGN_RESOURCE_NOT_EXISTS);
            }
        }
        // 删除老的分配的资源关系，然后添加新的分配的资源关系
        // 标记职务原资源关系都为删除
        positionResourceMapper.deleteByPositionId(positionId);
        // 创建 PositionResourceDO 数组，并插入到数据库
        if (!CollectionUtils.isEmpty(resourceIds)) {
            List<PositionResourceDO> PositionResources = resourceIds.stream()
                    .map(resourceId -> new PositionResourceDO().setPositionId(positionId).setResourceId(resourceId)).collect(Collectors.toList());
            positionResourceMapper.insertList(PositionResources);
        }
    }

    /**
     * 检查是否拥有权限
     * @param positionIds
     * @param permissions
     */
    public void checkPermission(Collection<String> positionIds, Collection<String> permissions) {
        // 查询权限对应资源
        List<ResourceDO> resourceBOs = resourceMapper.selectListByPermissions(permissions);
        if (CollectionUtil.isEmpty(resourceBOs)) { // 无对应资源，则认为无需权限验证
            log.warn("[checkPermission][permission({}) 未配置对应资源]", permissions);
            return;
        }
        Set<String> permissionIds = CollectionUtils.convertSet(resourceBOs, ResourceDO::getId);
        // 权限验证
        List<PositionResourceDO> positionResourceDOS = positionResourceMapper.selectListByResourceIds(permissionIds);
        if (CollectionUtil.isEmpty(positionResourceDOS)) { // 资源未授予任何职务，必然权限验证不通过
            throw new GlobalException(FORBIDDEN);
        }
        Map<String, List<String>> resourcePositionMap = CollectionUtils.convertMultiMap(positionResourceDOS,
                PositionResourceDO::getResourceId, PositionResourceDO::getPositionId);
        for (Map.Entry<String, List<String>> entry : resourcePositionMap.entrySet()) {
            if (!CollectionUtil.containsAny(positionIds, entry.getValue())) { // 所以有任一不满足，就验证失败，抛出异常
                throw new GlobalException(FORBIDDEN);
            }
        }
    }

}
